ServiceManager源码分析

ServiceManager是Android系统的服务大管家,它负责所有实名Server的管理,比如CameraService,WindowManagerService等等,所以它的重要性可想而知,ServiceManager是单独运行在一个系统进程中的,它在Init.rc的定义如下:

1
2
3
4
5
6
7
8
9
10
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm

Class 为core 属于核心级的 它的主方法在service_manager.c中定义 我们看看它的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
frameworks/native/cmds/servicemanager/service_manager.c
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
//打开binder 这里映射的内存大小为128k
bs = binder_open(128*1024);
//使sm成为所有服务的大管家
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}

svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);//binder循环
return 0;
}

进入主方法后,主要做了三件事:
<1>. 打开binder驱动设备,servicemanager的业务并不复杂,这里映射的大小为128k。
<2>. 调用binder_become_context_manager使sevicemanger成为所有实名服务的大管家
<3>. 调用binder_loop进入binder循环,等待client端的请求。svcmgr_handler为servicemanager服务处理handler,它是一个函数指针,主要是处理它自身的业务逻辑。比如我们的client端通过AddService或者getService的服务就是在这里进行处理的。

下面我们分析servicemanager的binder_loop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
frameworks/native/cmds/servicemanager/binder.c
void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
struct binder_write_read bwr;
unsigned readbuf[32];

bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;

readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(unsigned));
//不断的读取binder的内容
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (unsigned) readbuf;

res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);//读取binder内容

if (res < 0) {
ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
break;
}

res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);//解析数据
……
}
}

Binder_loop中首先通过binder_write向Binder驱动写入BC_ENTER_LOOPER,表示进入binder循环,然后通过BINDER_WRITE_READ读取binder内容,结果存放在一个binder_write_read结构中,然后开始通过binder_parse解析数据,这里将我们的服务处理函数传递给它,那么数据应该是在这里交给我们的handler进行处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
frameworks/native/cmds/servicemanager/binder.c
int binder_parse(struct binder_state *bs, struct binder_io *bio,
uint32_t *ptr, uint32_t size, binder_handler func)
{
……
switch(cmd) {
……
case BR_TRANSACTION: {
struct binder_txn *txn = (void *) ptr;
if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
ALOGE("parse: txn too small!\n");
return -1;
}
binder_dump_txn(txn);
if (func) {
unsigned rdata[256/4];
struct binder_io msg;
struct binder_io reply;
int res;

bio_init(&reply, rdata, sizeof(rdata), 4);
bio_init_from_txn(&msg, txn);
res = func(bs, txn, &msg, &reply);
binder_send_reply(bs, &reply, txn->data, res);
}
ptr += sizeof(*txn) / sizeof(uint32_t);
break;
}
……
}
}
return r;
}

可以看到在BR_TRANSACTION中的确是通过fun,也就是svcmgr_handler进行处理的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//sm的服务handler
frameworks/native/cmds/servicemanager/service_manager.c
int svcmgr_handler(struct binder_state *bs,
struct binder_txn *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
unsigned len;
void *ptr;
uint32_t strict_policy;
int allow_isolated;

if (txn->target != svcmgr_handle)
return -1;

strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,"invalid id %s\n", str8(s));
return -1;
}

switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
ptr = do_find_service(bs, s, len, txn->sender_euid);
if (!ptr)
break;
bio_put_ref(reply, ptr);
return 0;

case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
ptr = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
if (do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated))
return -1;
break;

case SVC_MGR_LIST_SERVICES: {
unsigned n = bio_get_uint32(msg);

si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si) {
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
default:
ALOGE("unknown code %d\n", txn->code);
return -1;
}

bio_put_uint32(reply, 0);
return 0;
}

Servicemanager作为服务的大管家它的业务并不负责,相比其他service的服务可以说是异常简单,我们看看它最重要的服务即添加服务和获取服务。

Servicemanager维护了一个svclist链表,每个添加进来的服务都会通过一个svcinfo进行描述,并添加到链表中。它的结构如下

1
2
3
4
5
6
7
8
9
10
11
struct svcinfo 
{
struct svcinfo *next;
void *ptr;//service的句柄
struct binder_death death;
int allow_isolated;
unsigned len;//服务名的长度
uint16_t name[0];//服务名
};

struct svcinfo *svclist = 0;//sm内部维护了一个svclist列表它是已经注册的服务列表

我们看看查找服务的过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len, unsigned uid)
{
struct svcinfo *si;
si = find_svc(s, len);
if (si && si->ptr) {
if (!si->allow_isolated) {
// If this service doesn't allow access from isolated processes,
// then check the uid to see if it is isolated.
unsigned appid = uid % AID_USER;
if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
return 0;
}
}
return si->ptr;
} else {
return 0;
}
}

struct svcinfo *find_svc(uint16_t *s16, unsigned len)
{
struct svcinfo *si;

for (si = svclist; si; si = si->next) {
if ((len == si->len) &&
!memcmp(s16, si->name, len * sizeof(uint16_t))) {
return si;
}
}
return 0;
}

很简单,它在内部遍历链表,根据服务名进行查找如果找到返回对应的句柄si->ptr,否则返回0.

而添加服务的方法为do_add_service,它的实现如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
frameworks/native/cmds/servicemanager/service_manager.c
int do_add_service(struct binder_state *bs,
uint16_t *s, unsigned len,
void *ptr, unsigned uid, int allow_isolated)
{
struct svcinfo *si;

if (!ptr || (len == 0) || (len > 127))
return -1;

if (!svc_can_register(uid, s)) {
ALOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
str8(s), ptr, uid);
return -1;
}

si = find_svc(s, len);
if (si) {
if (si->ptr) {
ALOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
str8(s), ptr, uid);
svcinfo_death(bs, si);
}
si->ptr = ptr;
} else {
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
ALOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",
str8(s), ptr, uid);
return -1;
}
si->ptr = ptr;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
si->name[len] = '\0';
si->death.func = svcinfo_death;
si->death.ptr = si;
si->allow_isolated = allow_isolated;
si->next = svclist;
svclist = si;
}

binder_acquire(bs, ptr);
binder_link_to_death(bs, ptr, &si->death);
return 0;
}

添加服务的名称长度不能大于127,随后在svclist中查找服务是否已经存在,如果存在,则释放之前的服务实例,将最新的服务句柄赋值给ptr,否则服务不存在,就需要为新的服务创建svcinfo结构,并对其进行初始化。同时将其添加到svclist的头部。

坚持原创技术分享,您的支持将鼓励我继续创作!